#
# Copyright (c) 2023 supercell
#
# SPDX-License-Identifier: BSD-3-Clause
#

module Luce
  abstract class BlockSyntax
    # Return the regex used to identify the beginning of this block,
    # if any.
    abstract def pattern : Regex

    def can_end_block?(parser : BlockParser) : Bool
      true
    end

    def can_parse?(parser : BlockParser) : Bool
      pattern.matches? parser.current.content
    end

    abstract def parse(parser : BlockParser) : Node?

    def parse_child_lines(parser : BlockParser) : Array(Line?)
      # Grab all of the lines that form the block element
      child_lines = [] of Line?

      until parser.done?
        match = pattern.match(parser.current.content)
        break if match.nil?
        child_lines << parser.current
        parser.advance
      end

      child_lines
    end

    # Returns the block which interrupts current syntax parsing if there is one,
    # otherwise returns `nil`.
    #
    # Make sure to check if `parser#done?` is `false` first.
    def interrupted_by(parser : BlockParser) : BlockSyntax?
      parser.block_syntaxes.each do |syntax|
        return syntax if syntax.can_parse?(parser) && syntax.can_end_block?(parser)
      end
      nil
    end

    # Return whether or not *parser*'s current line should end the
    # previous block
    def self.at_block_end?(parser : BlockParser) : Bool
      return true if parser.done?
      parser.block_syntaxes.any? { |syntax| syntax.can_parse?(parser) && syntax.can_end_block?(parser) }
    end

    # Generates a valid HTML anchor from the inner text of *element*.
    def self.generate_anchor_hash(element : Element) : String
      # ameba:disable Lint/NotNil
      element.children.not_nil!.first.text_content
        .downcase
        .strip
        .gsub(/[^a-z0-9 _-]/, "")
        .gsub(/\s/, "-")
    end
  end
end
